﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
class StreamSaveData
{
    public StreamSaveData()
    {
        m_stream = new MemoryStream();
    }

    public void Write(String strData)
	{
        byte[] bData = System.Text.Encoding.Default.GetBytes(strData);
        Write(bData);
    }
    public void Write(byte[] bData)
    {
        int iDataLength = bData.Length;
        Write(iDataLength);
        m_stream.Write(bData, 0, bData.Length);
    }
    public void Write<T>( T iData)
    {
         Type tx = iData.GetType();
        Type[] types = new Type[] { typeof(StreamSaveData).MakeByRefType() };
        MethodInfo mf = tx.GetMethod("Write", types);
        if (mf != null)
        {
            object[] pParam = new object[1];
            pParam[0] = this;
            mf.Invoke(iData, pParam);
        }
        else
        {
            byte[] buff = new byte[Marshal.SizeOf(iData)];
            IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(iData));
            Marshal.StructureToPtr(iData, intPtr, true);
            Marshal.Copy(intPtr, buff, 0, buff.Length);
            m_stream.Write(buff, 0, buff.Length);
            Marshal.FreeHGlobal(intPtr);
        }
    }
    private MemoryStream m_stream;
   public  byte[] GetData()
    {
        return m_stream.ToArray();
    }
}

class StreamLoadData
{
    public StreamLoadData(ref byte[] bData, int iFrom =0 ,int iCount = -1)
    {
        if (iCount < 0) iCount = bData.Length;
        m_stream = new MemoryStream(bData, iFrom, iCount); ;
    }
    public void Read<T>(ref T iData)
    {
        Type tx = iData.GetType();
        Type[] types = new Type[] { typeof(StreamLoadData).MakeByRefType() };
        MethodInfo mf = tx.GetMethod("Read", types);
        if (mf != null)
        {
            object[] pParam = new object[1];
            pParam[0] = this;
            mf.Invoke(iData, pParam);
        }
        else
        {
            byte[] buff = new byte[Marshal.SizeOf(iData)];
            m_stream.Read(buff, 0, buff.Length);
            IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);
            iData =  (T)(Marshal.PtrToStructure(ptr, typeof(T)));
        }
    }
    public void Read(ref String strData)
    {
        int iLength = 0;
        Read(ref iLength);
        if(iLength > 0)
        {
            byte[] pData = new byte[iLength ];
            m_stream.Read(pData, 0, iLength);
            strData = System.Text.Encoding.Default.GetString(pData);
        }
    }


    public bool IsEof()
    {
      return  m_stream.Position == m_stream.Length ;
    }
    private MemoryStream m_stream;
}